﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using DTO.Common;
using System.ServiceModel;

namespace DAO.Headquarter
{
    internal enum Operation { ADD, UPDATE }

    internal class StoresConfiguration
    {
        public string Endpoint { get; set; }
        public List<ProductType> ProductTypes { get; set; }
        public string EndpointConfigurationName { get; set; }
    }

    internal class ChannelFactoryStoresHelper
    {
        private static readonly Dictionary<Operation, List<StoresConfiguration>> storesConfig = new Dictionary<Operation, List<StoresConfiguration>>();

        internal static ChannelFactory<T> CreateChannelFactoryToStores<T>(Operation operation, ProductType type)
        {
            StoresConfiguration config = GetStoreConfiguration(operation, type);

            ChannelFactory<T> factory = new ChannelFactory<T>(
                config.EndpointConfigurationName,
                new EndpointAddress(config.Endpoint));

            return factory;
        }


        static ChannelFactoryStoresHelper() 
        {
            ProcessConfiguration(ConfigurationManager.AppSettings["AddStoresConfig"], Operation.ADD);
            ProcessConfiguration(ConfigurationManager.AppSettings["UpdateStoresConfig"], Operation.UPDATE);
        }

        private static void ProcessConfiguration(string configuration, Operation operation)
        {
            //Configuration example:
            //  Cloth type [+Cloth type]* - endpoint configured name - address
            //  #
            //  Cloth type [+Cloth type]* - endpoint configured name - address
             string[] stores = configuration.Split('#');
            foreach (string store in stores)
            {
                StoresConfiguration config = ProcessStoreConfiguration(store);
                if (!storesConfig.ContainsKey(operation))
                {
                    storesConfig.Add(operation, new List<StoresConfiguration>());
                }

                storesConfig[operation].Add(config);
            }
        }

        private static StoresConfiguration ProcessStoreConfiguration(string configuration)
        {
            //Configuration example
            //  Cloth type [+Cloth type]* - endpoint configured name - address

            string[] config = configuration.Split('-');
            string[] clothTypes = config[0].Split('+');
            
            //parse product types
            List<ProductType> productType = new List<ProductType>();
            foreach (string clothType in clothTypes)
            {
                ProductType type = (ProductType)Enum.Parse(typeof(ProductType), clothType);
                productType.Add(type);
            }

            return new StoresConfiguration
            {
                EndpointConfigurationName = config[1],
                Endpoint = config[2],
                ProductTypes = productType
            };

        }

        private static StoresConfiguration GetStoreConfiguration(Operation operation, ProductType type)
        {
            List<StoresConfiguration> config = storesConfig[operation];
            return config.Where(c => c.ProductTypes.Contains(type)).FirstOrDefault();
        }
    }
}
